package com.eeb.dropwizardmongo.example.resources;

import com.codahale.metrics.annotation.Timed;
import com.eeb.dropwizardmongo.example.api.Badge;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.mongojack.DBQuery;
import org.mongojack.DBUpdate;
import org.mongojack.JacksonDBCollection;

import javax.validation.Valid;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.Map;

@Path("/badges")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class BadgesResource {

    private JacksonDBCollection<Badge, String> badges;

    public BadgesResource(JacksonDBCollection<Badge, String> badges) {
        this.badges = badges;
    }

    @GET
    @Produces(value = MediaType.APPLICATION_JSON)
    @Timed
    public Response getBadges() {
        return Response.ok(badges.find().toArray()).build();
    }

    @Path("/{badge}")
    @GET
    @Produces(value = MediaType.APPLICATION_JSON)
    @Timed
    public Response getBadge(@PathParam("badge") String badge) throws UnsupportedEncodingException {
        return Response.ok(badges.findOne(DBQuery.is("name", URLEncoder.encode(badge, "UTF-8")))).build();
    }

    @POST
    @Timed
    public Response postBadge(@Valid Badge badge) throws URISyntaxException, UnsupportedEncodingException {
        URI uri = new URI("/" + badge.getName());
        if (badges.findOne(DBQuery.is("name", badge.getName())) == null)
            badges.insert(badge);
        return Response.created(uri).entity(badges.findOne(DBQuery.is("name", badge.getName()))).build();
    }

    @PUT
    @Timed
    public Response putBadge(@Valid Badge badge) {
        return Response.status(405).entity("PUT to /badges/{name} or POST to /badges").build();
    }

    @Path("/{badge}")
    @PUT
    @Timed
    public Response putBadge(@PathParam("badge") String badge,
                             @Valid String json) throws IOException {
        DBQuery.Query query = DBQuery.is("name", badge);
        Map<String, Object> map = new ObjectMapper().readValue(json, new TypeReference<Map<String, Object>>() {
        });
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() != null) {
                if (entry.getValue() instanceof String)
                    entry.setValue(URLEncoder.encode((String) entry.getValue(), "UTF-8"));
                badges.update(query, DBUpdate.set(entry.getKey(), entry.getValue()));
            }
        }
        return Response.ok(badges.findOne(DBQuery.is("name", badge))).build();
    }

    @Path("/{badge}")
    @DELETE
    @Timed
    public Response deleteBadge(@PathParam("badge") String badge) {
        badges.findAndRemove(DBQuery.is("name", badge));
        return Response.ok(badges.find().toArray()).build();
    }

}